import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';

export interface JwtPayload {
  sub: number;
  userId: number;
  username: string;
  iat?: number;
  exp?: number;
}

export interface TokenPair {
  accessToken: string;
  refreshToken: string;
  accessExpiresIn: number;
  refreshExpiresIn: number;
}

@Injectable()
export class JwtAuthService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
  ) {}

  /**
   * 生成访问令牌
   */
  generateAccessToken(payload: JwtPayload): string {
    return this.jwtService.sign(payload, {
      secret:
        this.configService.get<string>('jwt.accessSecret') ||
        'access-secret-key',
      expiresIn: this.configService.get<string>('jwt.accessExpiresIn') || '15m',
    });
  }

  /**
   * 生成刷新令牌
   */
  generateRefreshToken(payload: JwtPayload): string {
    return this.jwtService.sign(payload, {
      secret:
        this.configService.get<string>('jwt.refreshSecret') ||
        'refresh-secret-key',
      expiresIn: this.configService.get<string>('jwt.refreshExpiresIn') || '7d',
    });
  }

  /**
   * 生成令牌对
   */
  generateTokenPair(user: { id: number; username: string }): TokenPair {
    const payload: JwtPayload = {
      sub: user.id,
      userId: user.id,
      username: user.username,
    };

    const accessToken = this.generateAccessToken(payload);
    const refreshToken = this.generateRefreshToken(payload);

    const accessExpiresIn = this.parseExpiresIn(
      this.configService.get<string>('jwt.accessExpiresIn') || '15m',
    );
    const refreshExpiresIn = this.parseExpiresIn(
      this.configService.get<string>('jwt.refreshExpiresIn') || '7d',
    );

    return {
      accessToken,
      refreshToken,
      accessExpiresIn,
      refreshExpiresIn,
    };
  }

  /**
   * 验证访问令牌
   */
  async verifyAccessToken(token: string): Promise<JwtPayload> {
    return this.jwtService.verifyAsync(token, {
      secret: this.configService.get<string>('jwt.accessSecret'),
    });
  }

  /**
   * 验证刷新令牌
   */
  async verifyRefreshToken(token: string): Promise<JwtPayload> {
    return this.jwtService.verifyAsync(token, {
      secret: this.configService.get<string>('jwt.refreshSecret'),
    });
  }

  /**
   * 解析过期时间字符串为秒数
   */
  private parseExpiresIn(expiresIn: string): number {
    const units: { [key: string]: number } = {
      s: 1,
      m: 60,
      h: 3600,
      d: 86400,
      w: 604800,
      y: 31536000,
    };

    const match = expiresIn.match(/^(\d+)([smhdwy])$/);
    if (!match) {
      throw new Error(`Invalid expiresIn format: ${expiresIn}`);
    }

    const value = parseInt(match[1], 10);
    const unit = match[2];

    return value * units[unit];
  }
}
